#include "board.h"
#include "drv_touch.h"
#include "drv_touch_ns2009.h"

#if TOUCH_USE_NS2009

void touch_ns2009_init(void) 
{
	
}

#define NS2009_TS_ADDR   0x48
#define NS2009_IOCTL_SET_CALBRATION         0x1

enum
{
    NS2009_LOW_POWER_READ_X = 0xc0,
    NS2009_LOW_POWER_READ_Y = 0xd0,
    NS2009_LOW_POWER_READ_Z1 = 0xe0,
    NS2009_LOW_POWER_READ_Z2 = 0xf0,
};

struct rt_i2c_bus_device *i2c_bus;

static int ns2009_i2c_WR(struct rt_i2c_bus_device * dev, uint8_t *reg, int wlen, uint8_t * buf, int rlen)
{
    struct rt_i2c_msg msgs[2];
    int ret;

    msgs[0].addr = dev->addr;
    msgs[0].flags = RT_I2C_WR;
    msgs[0].len = wlen;
    msgs[0].buf = reg;

    msgs[1].addr = dev->addr;
    msgs[1].flags = RT_I2C_RD;
    msgs[1].len = rlen;
    msgs[1].buf = buf;
    //此处直接调用drv_i2c中的方法，请保证没有线程冲突
    //原始i2c_transfer(dev->i2c, msgs, 2) 如果在中断中调用，会因为锁问题停止
    ret=ingenic_i2c_xfer(dev, msgs, 2);//this must 2

    //return ret;// < 0 ? ret : (ret != 2 ? -EIO : 0);
    return 0;
}

static uint8_t ns2009_read(uint8_t cmd, uint32_t *val)
{
    uint8_t buf[2];
    
    ns2009_i2c_WR(i2c_bus, &cmd, 1, buf, 2);
    // if (ret != 0)
    //     return 0;
    if (val)
        *val = (buf[0] << 4) | (buf[1] >> 4);
    return 1;
}


void ns2009_hw_reset(rt_uint8_t address)
{
    // gpio_set_func(TP_RST_PIN,IO_OUTPUT);
    // gpio_direction_output(TP_RST_PIN,0);
    // rt_thread_mdelay(20);//T2>=10ms
    // //HIGH: 0x14,
    // gpio_set_func(TP_INT_PIN,IO_OUTPUT);
    // gpio_direction_output(TP_INT_PIN,1);

    // rt_thread_mdelay(1);//T3>=100us

    // gpio_direction_output(TP_RST_PIN,1);
    // rt_thread_mdelay(8);//T4>=5ms
    // //  rt_pin_write(TP_INT_PIN, PIN_LOW);
    // //  rt_thread_mdelay(50);//50ms将INT悬浮输入
    // gpio_set_pull_mode(TP_INT_PIN,PULL_DISABLE);
    // //   gpio_set_func(GPIO_PORT_E,GPIO_PIN_3,IO_INPUT);
    gpio_direction_input(TP_INT_PIN);
    // // rt_pin_mode(TP_INT_PIN, PIN_MODE_INPUT);
}


static uint32_t touch_x_min = 300;
static uint32_t touch_x_max = 3800;
static uint32_t touch_y_min = 560;
static uint32_t touch_y_max = 3510;
static uint32_t touch_dir  = 0;

static uint32_t screen_x = 480;
static uint32_t screen_y = 272;
static uint32_t screen_dir = 0;

int touch_get_raw(uint32_t *raw_x,uint32_t *raw_y)
{
    ns2009_read(NS2009_LOW_POWER_READ_X, raw_x);
    ns2009_read(NS2009_LOW_POWER_READ_Y, raw_y);
	return 1;
}


void touch_raw_to_xy(uint32_t raw_x,uint32_t raw_y,uint32_t *x,uint32_t *y)
{
	if(raw_x < touch_x_min) raw_x = touch_x_min;
	if(raw_x > touch_x_max) raw_x = touch_x_max;

	if(raw_y < touch_y_min) raw_y = touch_y_min;
	if(raw_y > touch_y_max) raw_y = touch_y_max;
	
	switch(touch_dir)
	{
		case 0:
			*x = (raw_x - touch_x_min) * screen_x / (touch_x_max - touch_x_min);
			*y = (raw_y - touch_y_min) * screen_y / (touch_y_max - touch_y_min);
			break;
		case 1:
			*x = (raw_x - touch_x_min) * screen_x / (touch_x_max - touch_x_min);
			*y = (touch_y_max - raw_y) * screen_y / (touch_y_max - touch_y_min);
			break;
		case 2:
			*x = (touch_x_max - raw_x) * screen_x / (touch_x_max - touch_x_min);
			*y = (touch_y_max - raw_y) * screen_y / (touch_y_max - touch_y_min);
			break;
		case 3:
			*x = (touch_x_max - raw_x) * screen_x / (touch_x_max - touch_x_min);
			*y = (raw_y - touch_y_min) * screen_y / (touch_y_max - touch_y_min);
			break;
	}
}



static void ns2009_interrupt(void * data){

    on_touch_message_handle on_touch_callback=(on_touch_message_handle)data;
    uint32_t x = 0, y = 0, z1 = 0;
    uint32_t raw_x = 0 ;
    uint32_t raw_y = 0 ;
    static struct touch_message msg;
    static rt_uint8_t s_tp_down = 0;

    gpio_irq_disable(TP_INT_PIN);
    //rt_kprintf("ns2009 isr\n");
    if (ns2009_read(NS2009_LOW_POWER_READ_Z1, &z1))
    {
        if ((z1 > 80) && (z1 < 2000))
        {
            touch_get_raw(&raw_x,&raw_y);
            touch_raw_to_xy(raw_x,raw_y,&x,&y);
            //tsfilter_update(ts_ns2009_pdata->filter, &x, &y);
            msg.x = x;
            msg.y = y;
            //rt_kprintf("X:%d Y:%d\n",x,y);

            if(s_tp_down)
            {
                msg.event = TOUCH_EVENT_MOVE;
            }
            else
            {
                msg.event = TOUCH_EVENT_DOWN;
                s_tp_down = 1;
            }
        }
        else
        {
            if(s_tp_down)
            {
                s_tp_down = 0;
            }
            msg.event = TOUCH_EVENT_UP;
        }
    }else
    {
        msg.event = TOUCH_EVENT_NONE;
    }
    if(on_touch_callback!=RT_NULL)
    {
        on_touch_callback(&msg);
    }
    gpio_irq_enable(TP_INT_PIN);
}

static int ns2009_probe()
{
  //  gpio_irq_enable(TP_INT_PIN);

    i2c_bus = rt_i2c_bus_device_find(TOUCH_I2C_NAME);
    RT_ASSERT(i2c_bus);

    if(rt_device_open(&i2c_bus->parent, RT_DEVICE_OFLAG_RDWR) != RT_EOK)
    {
        TPDEBUG("[TP] %s I2C not open error!\n", TOUCH_I2C_NAME);
        return 0;
    }
    i2c_bus->addr=NS2009_TS_ADDR;
    ns2009_hw_reset(NS2009_TS_ADDR);
    return 0;
}
void start_touch_listen(on_touch_message_handle call_back){
    gpio_set_func(TP_INT_PIN,IO_FUN_5);
    gpio_set_irq_type(TP_INT_PIN,NEGATIVE);
    gpio_set_irq_callback(TP_INT_PIN,ns2009_interrupt,call_back);
    gpio_irq_enable(TP_INT_PIN);
}


int touch_read_status(struct touch_message *msg)
{
    uint32_t x = 0, y = 0, z1 = 0;
    uint32_t raw_x = 0 ;
    uint32_t raw_y = 0 ;
    //static rt_uint8_t s_tp_down = 0;

    if(gpio_get_value(TP_INT_PIN)==0)
    {

    }

    if (ns2009_read(NS2009_LOW_POWER_READ_Z1, &z1))
    {
        if ((z1 > 80) && (z1 < 2000))
        {
            touch_get_raw(&raw_x,&raw_y);
            touch_raw_to_xy(raw_x,raw_y,&x,&y);
            msg->x = x;
            msg->y = y;
            msg->event = TOUCH_EVENT_DOWN;
        }
        else
        {
            msg->event = TOUCH_EVENT_UP;
        }
    }else
    {
        msg->event = TOUCH_EVENT_NONE;
    }
    return 0;
}

#endif
